home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 October: Windmill on DISC / ADC Developer CD (1993-10) (''Windmill On DISC'')_iso / Dev.CD Oct 93.iso / System Software / U.S. System Software / System 7 Pro™ Beta 11 / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / gatewayget.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-28  |  7.8 KB  |  321 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        10/29/92    update to a11            a11
  15. SJF        06/08/92    update to a8            a8
  16. SJF        02/15/92    first working version    a4.5
  17. SJF        10/16/91    initial coding            a3
  18.  
  19. ---------------------------------------------------------------------*/
  20.  
  21. #ifndef  __OCE__
  22. #include <OCE.h>
  23. #endif
  24.  
  25. #ifndef __OCEMAIL__
  26. #include <OCEMail.h>
  27. #endif
  28.  
  29. #include "const.h"
  30. #include "gwerrors.h"
  31. #include "mytypes.h"
  32. #include "globals.h"
  33. #include "utils.h"
  34. #include "spoolsystem.h"
  35. #include "gatewaystuff.h"
  36. #include "authstuff.h"
  37. #include "errorhandling.h"
  38.  
  39. #include "spooltoexternal.h"
  40. #include "spoolfromaoce.h"
  41. #include "spooltoaoce.h"
  42. #include "reports.h"
  43.  
  44. #include "gatewayget.h"
  45.  
  46.  
  47. // PeriodicCheckGet
  48. //
  49. // when the toolbox thinks that it's time to check for mail, this function is called, in addition
  50. // to being called on startup of the gateway
  51. //
  52. OSErr PeriodicCheckGet(void)
  53. {
  54.     short slotIndex,arrIndex;
  55.     SlotSpec *slotSpec;
  56.     OSErr err = noErr;
  57.     unsigned long dateTime;
  58.     
  59.     TraceExecution("\pPeriodicCheckGet");
  60.  
  61.     GetDateTime(&dateTime);    
  62.  
  63.     for (slotIndex = arrIndex = 0; (err==noErr) && (slotIndex<gNumSlots); arrIndex++) {
  64.         if (gSlotDatabase[arrIndex].active && gSlotDatabase[arrIndex].enabled) {    // if the slot is in use, process it
  65.             slotIndex++;
  66.             slotSpec = &gSlotDatabase[arrIndex];
  67.             if (slotSpec->dirIdentity.valid) {
  68.                 EnterAuthCriticalSection();    // don't allow locking of local identity while we're here
  69.                 if (TimeToCheckGet(&slotSpec->stdInfo.sendReceiveTimer,slotSpec->lastCheckGet,dateTime)) {
  70.                     err = DoSlotGet(slotSpec);
  71.                     if (err==noErr)
  72.                         slotSpec->lastCheckGet = dateTime;
  73.                 }
  74.                 ExitAuthCriticalSection();
  75.             }
  76.         }
  77.     }
  78.     return err;
  79. }
  80.  
  81.  
  82. // TimeToCheckGet
  83. //
  84. // returns true if it's time to check for mail.  this function assumes the mailtimers are
  85. // in minutes, not seconds, since this seems to be what the toolbox is using for its scheduling
  86. // of eppcs.  note that the OCEMail.h header file specifies that these values are in seconds.
  87. //
  88. Boolean TimeToCheckGet(MailTimers *mailTimer,unsigned long lastCheck,unsigned long curTime)
  89. {
  90.     DateTimeRec dtRec;
  91.     unsigned long midnightSecs;    
  92.  
  93.     switch (mailTimer->sendTimeKind) {
  94.         case kMailTimerOff:
  95.             return false;                    // never check if there is no interval
  96.             break;
  97.         case kMailTimerFrequency:            // check if past frequency+lastCheck
  98.             return ((lastCheck + (60*mailTimer->send.frequency))<curTime);
  99.             break;
  100.         case kMailTimerTime:                // check at a specific time
  101.             if ((lastCheck + kOneDaySecs) > curTime)
  102.                 return false;
  103.             Secs2Date(curTime,&dtRec);    // get date of last midnight
  104.             dtRec.hour = 0;
  105.             dtRec.minute = 0;
  106.             dtRec.second = 0;
  107.             Date2Secs(&dtRec,&midnightSecs);
  108.             return ( (midnightSecs+(60*mailTimer->send.connectTime)) > curTime );
  109.             break;
  110.     }
  111.     return false;        
  112. }
  113.  
  114.  
  115. // DoSlotGet
  116. //
  117. // when we've determined that it's actually time to do a "get" (send to external system) this
  118. // function is called by PeriodicCheckGet.
  119. //
  120. OSErr DoSlotGet(SlotSpec *slot)
  121. {
  122.     OSErr err,enumErr,err2;
  123.     MSAMEnumeratePB gwp;
  124.     EnumOutQReply enumBlock;
  125.     long nextMsgSeq;
  126.     MailMsgRef msgRef;
  127.     FSSpec spoolSpec;
  128.     
  129.     TraceExecution("\pDoSlotGet");
  130.     
  131.     // first, we pull all the pending letters out of the AOCE slot and spool them
  132.     
  133.     nextMsgSeq = 1;
  134.     
  135.     err = noErr;
  136.     
  137.     do {
  138.         gwp.ioCompletion = (ProcPtr)MSAMCompletion;
  139.         gwp.queueRef  = slot->outQueue;
  140.         gwp.startSeqNum = nextMsgSeq;
  141.         gwp.buffer.bufferSize = sizeof(EnumOutQReply);
  142.         gwp.buffer.buffer = (Ptr)&enumBlock;
  143.         MSAMEnumerate((MSAMParam *)&gwp,true);
  144.         enumErr = WaitPBDone(&gwp);
  145.         nextMsgSeq = gwp.nextSeqNum;
  146.         if (enumErr==noErr && gwp.buffer.dataSize>sizeof(short) && (enumBlock.message.done==false)) {
  147.         
  148.             err = CreateSpoolFile(&spoolSpec);    // make our spool file
  149.             if (err!=noErr)
  150.                 break;
  151.             
  152.             // here, the message is spooled to the common data area, and then sent to the external gateway
  153.                         
  154.             err = GetSlotMessage(slot->outQueue,&enumBlock.message,&msgRef,&spoolSpec);
  155.             if (err==noErr) {
  156.                 err = SpoolToExternalGW(&spoolSpec,slot);
  157.                 err2 = DoneSlotMessage((err==noErr),slot->outQueue,&enumBlock.message,&spoolSpec,msgRef);
  158.                 if (err==noErr)
  159.                     err = err2;
  160.             }
  161.             
  162.             if (err!=noErr) {
  163.                 RemoveSpoolFile(&spoolSpec);
  164.                 break;
  165.             }
  166.                 
  167.             err = RemoveSpoolFile(&spoolSpec);
  168.             if (err!=noErr)
  169.                 break;
  170.         }
  171.     }
  172.     while (enumErr==noErr && nextMsgSeq!=0);
  173.     
  174.     // error retry mechanism- only report errors after we fail a number of times
  175.     // specified in kAllowedRetries
  176.     
  177.     err = RetrySlotError(err,slot,false);
  178.  
  179.     return err;
  180. }
  181.  
  182.  
  183. OSErr GetSlotMessage(MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,MailMsgRef *retMsgRef,FSSpec *spoolSpec)
  184. {
  185.     OSErr err;
  186.     MSAMParam gwp;
  187.     MailMsgRef msgRef;
  188.     
  189.     // mark message as being sent
  190.     
  191.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  192.     gwp.pmsamSetStatus.queueRef = qid;
  193.     gwp.pmsamSetStatus.seqNum = msg->seqNum;
  194.     gwp.pmsamSetStatus.msgHint = 0;
  195.     gwp.pmsamSetStatus.status = kPMSAMStatusSending;
  196.     err = PMSAMSetStatus(&gwp,true);
  197.     err = WaitPBDone(&gwp);
  198.     if (err!=noErr)
  199.         return err;
  200.  
  201.     // open message
  202.     
  203.     gwp.msamOpen.queueRef  = qid;                        
  204.     gwp.msamOpen.seqNum = msg->seqNum;
  205.     MSAMOpen(&gwp,true);
  206.     err = WaitPBDone(&gwp);
  207.     if (err!=noErr) {
  208.         return err;
  209.     }
  210.     msgRef = gwp.msamOpen.mailMsgRef;
  211.     
  212.     // put message into spool area
  213.     
  214.     err = SpoolFromAOCE(msgRef,spoolSpec);
  215.     if (err!=noErr) {
  216.         // might log this error with error reporting log
  217.         // close message
  218.         gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  219.         gwp.msamClose.mailMsgRef = msgRef;
  220.         MSAMClose(&gwp,true);    
  221.         WaitPBDone(&gwp);
  222.     }
  223.     
  224.     *retMsgRef = msgRef;
  225.     return err;
  226. }
  227.  
  228.  
  229. // we mark recipients, send delivery reports, close the message
  230. //
  231. // *** NOTE
  232. //
  233. // a14 and later note:  we no longer delete the outging messages from the queue
  234. // as per the "Public API deltas" document corresponding to the queue mgr redesign
  235. //
  236. // ********
  237.  
  238. OSErr DoneSlotMessage(Boolean sent,MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,FSSpec *spoolSpec,MailMsgRef msgRef)
  239. {
  240.     MSAMParam gwp;
  241.     OSErr err;
  242.     unsigned long bufferLen;
  243.     short recipientIndex,spoolIndex;
  244.     
  245.     // send the recipient reports for all recipients
  246.     
  247.     err = GenerateDeliveryReport(sent,spoolSpec);
  248.     if (err!=noErr)
  249.         return err;
  250.         
  251.     // mark each recipient
  252.     
  253.     for (spoolIndex=0,err=noErr; err==noErr; spoolIndex++) {
  254.         bufferLen = sizeof(short);
  255.         err = GetFromSpool(spoolSpec,kRecipientType,kReportCreator,spoolIndex,(Ptr)&recipientIndex,&bufferLen,0);
  256.         if (err==noErr) {
  257.             err = MarkRead(qid,msg->seqNum,recipientIndex);
  258.             if (err!=noErr)
  259.                 return err;
  260.         }
  261.     }
  262.     
  263.     // close message
  264.     
  265.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  266.     gwp.msamClose.mailMsgRef = msgRef;
  267.     MSAMClose(&gwp,true);    
  268.     err = WaitPBDone(&gwp);
  269.     if (err!=noErr)
  270.         return err;
  271.     
  272.     // change status to error if it didn't send
  273.     
  274.     if (!sent) {
  275.         gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  276.         gwp.pmsamSetStatus.queueRef = qid;
  277.         gwp.pmsamSetStatus.seqNum = msg->seqNum;
  278.         gwp.pmsamSetStatus.msgHint = 0;
  279.         gwp.pmsamSetStatus.status = kPMSAMStatusError;
  280.         err = PMSAMSetStatus(&gwp,true);
  281.         err = WaitPBDone(&gwp);
  282.         if (err!=noErr)
  283.             return err;
  284.     }
  285.     
  286.     // mark that we sent message
  287.     
  288.     msg->done = true;
  289.     return err;                                
  290. }
  291.  
  292.  
  293.  
  294. OSErr MarkRead(MSAMQueueRef qid,long seqNum,short recipIndex)
  295. {
  296.     MSAMMarkRecipientsPB gwp;
  297.     short markMsgs[2];
  298.     OSErr err;
  299.     
  300.     TraceExecution("\pMarkRead");
  301.     
  302.     markMsgs[0] = 1;                // count
  303.     markMsgs[1] = recipIndex;        // index to mark
  304.     
  305.     gwp.ioCompletion = (ProcPtr)MSAMCompletion;
  306.     gwp.queueRef = qid;
  307.     gwp.seqNum = seqNum;
  308.     gwp.buffer.buffer = (Ptr)markMsgs;
  309.     gwp.buffer.bufferSize = sizeof(short) + sizeof(short);
  310.  
  311.     MSAMMarkRecipients((MSAMParam *)&gwp,true);
  312.     err = WaitPBDone(&gwp);
  313.     
  314.     if (err==kOCEInvalidIndex) {
  315.         DebugStr("\pGot kOCEInvalidIndex");
  316.     }
  317.     
  318.     return err;
  319. }
  320.  
  321.